using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using CoreCalc.SheetDefinedFunctions;
using Version=CoreCalc.SheetDefinedFunctions.MarkLevel;

namespace CoreCalc.Benchmarks
{
    public class Benchmarks
    {
        private TextWriter tw;
        public bool useLog;

        public Benchmarks(bool useLog)
        {
            this.useLog = useLog;
        }

        private TextWriter Tw
        {
            get
            {
                if (tw == null) 
                  tw = new StreamWriter("benchmark_results.txt");
                return tw;
            }
        }

        public void BenchmarkWholeWorkbook(Workbook wb, int runs, Version markVersion)
        {
            Sheet paramSheet = null;
            foreach(var x in wb) {
                if (x.Name == "Param")
                {
                    paramSheet = x;
                    break;
                }
            }


            if(paramSheet != null)
            for (int i = 0; i < 10; i++)
            {
                var cell = paramSheet[0, i] ;
                string name = null;
                if (cell is TextCell)
                {
                    name = (paramSheet[0, i] as TextCell).value.value;
                }
                else if(cell is QuoteCell){
                    name = (paramSheet[0, i] as QuoteCell).value.value;
                }

                if(name != null) {
                    int start = (int)((NumberCell)paramSheet[1, i]).value.value;
                    int end = (int)((NumberCell)paramSheet[2, i]).value.value;
                    int step = (int)((NumberCell)paramSheet[3, i]).value.value;
                    for(int j = start;j <= end;j+=step) {
                        paramSheet[4, i] = new NumberCell((double)j);
                        BenchmarkGeneric(runs, markVersion, wb.Recalculate, name, j);
                    }
                }
            }
            else
                BenchmarkGeneric(runs, markVersion, wb.Recalculate, "", 0);






            
        }

        private void BenchmarkGeneric(int runs,
            Version markVersion, Act benchmark, string factorname, int j)
        {
//            Log("=== Benchmark generic called: "+markVersion+" ===");
            SdfManager.MarkLevel = markVersion;
            
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Reset();
            stopwatch.Start();

            for (int i = 0; i < runs; i++)
                benchmark();
            stopwatch.Stop();
            double average = (1E6*stopwatch.ElapsedMilliseconds)/runs;
            Log(String.Format("{0};{1};{2};{3};{4}", 
                Function.target == Function.TargetPlatform.CPU ? "CPU" : "GPU",
                factorname,
                j,
                runs,
                average

                              ));
        }
        //log both a flat file and console
        private void Log(string s)
        {
            if (useLog)
            {
                Console.WriteLine(s);
                Tw.WriteLine(s);
                Tw.Flush(); 
            }
        }


    }
}
